package com.liusy.taskengine.resultmodel;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.LinkedList;
import java.util.NoSuchElementException;

import org.apache.log4j.Logger;

import com.liusy.jdbc.JdbcHelp;
import com.liusy.taskengine.TaskManager;
import com.liusy.taskengine.listeners.AbstractResultCountListener;
import com.liusy.taskengine.listeners.IResultFinishListener;


/**
	结果处理者
 * 
 * @author liusy 2013-04-16
 */
public abstract class  AbstractResultModel extends Thread implements IResultModel{

	private static Logger log = Logger.getLogger(AbstractResultModel.class);
	//结果集合
	//protected Vector<ComparResult> comparResults = new Vector<ComparResult>();
	protected LinkedList<ComparResult> comparResults = new LinkedList<ComparResult>();
	
	//protected  Queue<ComparResult> comparResults = new ConcurrentLinkedQueue<ComparResult>();
	//protected ConcurrentSkipListSet<ComparResult> comparResults = new ConcurrentSkipListSet<ComparResult>();
	
	//管理工具
	protected TaskManager taskManager = null;
	
	//使用的数据库链接
	protected String aliasConnection = "";

	//使用的保存文件路径
	protected String filePath = "";
	
	//结果的大小（结果大小==任务大小）
	private int resultCount = 0;
	
	
	
	
	private  FileChannel writer = null;
	private byte [] b =null;
	private long position = 0;
	private ByteBuffer byteBuffer = null; 
	private String content = null;
	
	
	
	private Connection conn =	null;
	private Statement stmt = null;
	private long batchSqlCount = 0;
	private String sql = null;
	
	
	
	
	private IResultFinishListener startExecuteListener= null;
	private AbstractResultCountListener resultCountListener= null;
	private IResultFinishListener endExecuteListener= null;
	
	
	
	public void addStartExecuteListener(IResultFinishListener startExecuteListener) {
		this.startExecuteListener = startExecuteListener;
	}

	public void addResultCountListener(AbstractResultCountListener resultCountListener) {
		this.resultCountListener = resultCountListener;
	}

	public void addEndExecuteListener(IResultFinishListener endExecuteListener) {
		this.endExecuteListener = endExecuteListener;
	}

	public AbstractResultModel(String aliasConnection,String filePath)
	{
		this.aliasConnection = aliasConnection;
		this.filePath = filePath;
		
		if(null !=aliasConnection && !this.aliasConnection.equals(""))
		{
			conn = JdbcHelp.getJdbcHelp().getConnection(aliasConnection);
			try {
				if(null ==conn)
				{
					log.info("数据库链接：["+aliasConnection+"],不能得到。请检查.....");
					System.exit(0);
				}
				stmt=conn.createStatement();
				conn.setAutoCommit(false);
			} catch (SQLException e) {
				log.info(e.getMessage());
			}
		}
		if(null !=filePath && !this.filePath.equals(""))
		{
			try {
			   this.writer = new RandomAccessFile(filePath,"rw").getChannel();   
			} catch (FileNotFoundException e) {
				log.info(e.getMessage());
				System.exit(0);
			}
		}
	}
	
	public int getResultCount()
	{
		return this.resultCount;
	}
	
	public synchronized void addComparResults(ComparResult comparResult)
	{
		this.resultCount++;
		comparResults.add(comparResult);
	}

	@Deprecated
	@Override
	public synchronized void start() {
		// TODO Auto-generated method stub
		super.start();
	}
	
	public synchronized void start(TaskManager tm) {
		taskManager =tm;
		super.start();
	}
	
	@Override
	public void run() {
	
		if(null!=startExecuteListener)
		{
			startExecuteListener.StartExecuteListener(this);
		}
		ComparResult comparResult = null;
		while (null!=taskManager) {
			if(null!=resultCountListener && !resultCountListener.isAlreadyExecute())
			{
				resultCountListener.setAlreadyExecute(true);
				resultCountListener.ResultCountListener(this);
			}
			try {
				comparResult= comparResults.poll();
			} catch (NoSuchElementException e) {
				// TODO: handle exception
			}
			
				if(null!=comparResult)
				{
					ResultHandle(comparResult);
					comparResult = null;
				}
		}
		for (ComparResult comparResult_ : comparResults) {
			ResultHandle(comparResult_);
		} 
		
		if(null!=endExecuteListener)
		{
			endExecuteListener.EndExecuteListener(this);
		}
		
		
		log.info(" -----------------------------结束--------------------------");
		
		try {
			
			resultFinishClear();
			
			this.interrupt();
			
		} catch (Exception e) {
			resultFinishClear();
			log.error(e.getMessage());
		} finally{
			resultFinishClear();
		}
		
	}
	
	public void ResultHandle(ComparResult comparResult)
	{
		try {
			if(null!=conn)
				DbResultHandle(conn, comparResult);
			if(null!=this.writer)
				FileResultHandle(writer,comparResult);
		} catch (Exception e) {
			log.info("保存结果出现错误："+e.getMessage());
		}
	}
	
	@Override
	public void interrupt() {
		this.taskManager = null;
	}

	@Override
	public void FileResultHandle(FileChannel writer,ComparResult comparResult){
		try {
			content = FileResultString(comparResult);
			if(null!=content&&content.length()>0)
			{
				b = content.getBytes("utf-8");
				byteBuffer = writer.map(FileChannel.MapMode.READ_WRITE, position,(position + b.length));   
				byteBuffer.put(b);
				position += b.length;
				byteBuffer.clear();
				content = null;
			}
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	public String FileResultString(ComparResult comparResult){
		return (this.getResultCount()+"sql:"+comparResult.getExecutesqlModelSql()+"  resultCount: "+comparResult.getRowRusltListMap().size()+"\n");
	}
	
	
	@Override
	public void DbResultHandle(Connection conn,ComparResult comparResult){
		try {
			
		     sql = DbResultString(comparResult);
		 	if(null!=sql&&sql.length()>0)
			{
		 		stmt.addBatch(sql);
		 		batchSqlCount++;
			}
		 	if(batchSqlCount>=50)
		 	{
		 		stmt.executeBatch();
		 		conn.commit();
		 	}
	        
		} catch (Exception e) {
			log.info(e.getMessage());
		}
   
	}

	
	@Override
	public String DbResultString(ComparResult comparResult){
//		if(comparResult.getRowRusltListMap().size()==0)
//		return "insert into aa(value) values('客户编号为：【"+comparResult.getRowTaskMap().get("name")+"】在目标表中出现  【0】次，【】')";
//		return "insert into aa(value) values('客户编号为：【"+comparResult.getRowTaskMap().get("name")+"】在目标表中出现  【"+comparResult.getRowRusltListMap().size()+"】次，【"+comparResult.getRowRusltListMap().get(0).get("CUSTOMERID")+"')";
		return "insert into aa(value) values('"+comparResult.getRowTaskMap().get("name")+"')";

	}
	
	@Override
	public void resultFinishClear() {
		try {
			b = null;
			position = 0;
			if (null != byteBuffer)
				unmap(byteBuffer);
			byteBuffer = null;
			if (null != this.writer)
				writer.close();
			if (stmt != null) {
				stmt.executeBatch();
				stmt.close();
				stmt = null;
			}
			if (conn != null) {
				conn.commit();
				conn.close();
				conn = null;
			}
		} catch (Exception e) {
			log.info(e.getMessage());
		}
	}
	
	
	public static void mappedBuffer() throws IOException{   
        FileChannel read = new FileInputStream("G://lily_947.txt").getChannel();   
        FileChannel writer = new RandomAccessFile("G://buffer.tmp","rw").getChannel();   
        long i = 0;   
        long size = read.size()/30;   
        ByteBuffer bb,cc = null;   
        while(i<read.size()&&(read.size()-i)>size){   
            bb = read.map(FileChannel.MapMode.READ_ONLY, i, size);   
            cc = writer.map(FileChannel.MapMode.READ_WRITE, i, size);   
            cc.put(bb);   
            i+=size;   
            bb.clear();   
            cc.clear();   
        }   
        bb = read.map(FileChannel.MapMode.READ_ONLY, i, read.size()-i);   
        cc.put(bb);   
        bb.clear();   
        cc.clear();   
        read.close();   
        writer.close();   
           
    }  
	public static void unmap(final ByteBuffer buffer) {   
        if (buffer == null) {   
            return;   
        }   
        AccessController.doPrivileged(new PrivilegedAction<Object>() {   
            public Object run() {   
                try {   
                    Method getCleanerMethod = buffer.getClass().getMethod("cleaner", new Class[0]);   
                    if (getCleanerMethod != null) {   
                        getCleanerMethod.setAccessible(true);   
                        Object cleaner = getCleanerMethod.invoke(buffer, new Object[0]);   
                        Method cleanMethod = cleaner.getClass().getMethod("clean", new Class[0]);   
                        if (cleanMethod != null) {   
                            cleanMethod.invoke(cleaner, new Object[0]);   
                        }   
                    }   
                } catch (Exception e) {   
                    e.printStackTrace();   
                }   
                return null;   
            }   
    
        });   
    }  
}
